import sys
from pathlib import Path

base_path = str(Path(__file__).resolve().parent.parent)
sys.path.append(base_path)
import json
import time
from collections import OrderedDict
from functools import wraps


def log_decorator(log_path="log.txt"):
    def decorator(func):
        @wraps(func)
        def wrapprt(*args, **keys):
            log = {
                "time": time.time(),
                "function": func.__name__,
                "doc": func.__doc__,
                "args": args,
                "keys": keys,
                "result": "",
            }
            result = func(*args, **keys)
            log["result"] = result
            with open(log_path, "+a", encoding="utf-8") as f:
                f.write(json.dumps(log, ensure_ascii=False) + "\n")

        return wrapprt

    return decorator


def cache_decorator(cache_path="cache.txt", max_size=10):
    def decorator(func):
        try:
            with open(cache_path, "+r", encoding="utf-8") as f:
                cache = OrderedDict(json.loads(f))
        except Exception:
            cache = OrderedDict()

        @wraps(func)
        def wrapper(*args, **keys):
            key = json.dumps({"args": args, "keys": keys}, sort_keys=True)

            result = None
            if key in cache:
                print(f"命中缓存：{key} -> {cache[key]}")
                cache.move_to_end(key)
                result = cache[key]
            else:
                if len(cache) >= max_size:
                    first_key = next(iter(cache))
                    print(f"移除缓存：{first_key} -> {cache[first_key]}")
                    cache.pop(first_key)
                result = func(*args, **keys)
                cache[key] = result
                with open(cache_path, "w", encoding="utf-8") as f:
                    f.write(json.dumps(cache, ensure_ascii=False, indent=2))
            return result

        return wrapper

    return decorator


@log_decorator(log_path=f"{Path(__file__).parent.parent}/data/log.txt")
@cache_decorator(
    cache_path=f"{Path(__file__).parent.parent}/data/cache.txt", max_size=3
)
def compute(x, y):
    print(f"计算 {x}+{y}")
    return x + y


compute(1, 1)
# compute(2, 2)
# compute(3, 3)
# compute(4, 4)
# compute(2, 2)
